// FacebookIFrameSession.cs
// Facebook/FrameworkWeb/Web
// Copyright (c) 2007, Nikhil Kothari. All Rights Reserved.
//

using System;
using System.Diagnostics;
using System.Web;
using System.Web.UI;
using Facebook.Service.Core;

namespace Facebook.Web {

    internal sealed class FacebookIFrameSession : FacebookServerSession {

        private bool _stateLoaded;

        private string _sessionKeyState;
        private string _userIDState;
        private bool _sessionExpiresState;
        private string _pageUserIDState;

        private string _referrer;

        public FacebookIFrameSession(FacebookApplication application, string appKey, string secret)
            : base(application, appKey, secret) {
        }

        protected internal override string Initialize(HttpContext context) {
            base.Initialize(context);

            string redirectUrl = null;
            HttpRequest request = context.Request;

            FacebookSessionType sessionType = FacebookSessionType.User;

            string sessionKey = request["fb_sig_session_key"];
            bool sessionExpires = (String.CompareOrdinal(request["fb_sig_expires"], "0") != 0);
            string userID = request["fb_sig_user"];
            string pageUserID = null;

            if (String.IsNullOrEmpty(request["fb_page_id"]) == false) {
                pageUserID = userID;
                userID = request["fb_page_id"];
            }

            if (_stateLoaded &&
                (String.IsNullOrEmpty(sessionKey) || String.IsNullOrEmpty(userID))) {
                sessionKey = _sessionKeyState;
                sessionExpires = _sessionExpiresState;
                userID = _userIDState;
                pageUserID = _pageUserIDState;
            }

            if (String.IsNullOrEmpty(sessionKey) || String.IsNullOrEmpty(userID)) {
                string authToken = request["auth_token"];

                if (String.IsNullOrEmpty(authToken) == false) {
                    FacebookRequest sessionRequest = new FacebookRequest(this);
                    string dummy;

                    sessionKey = sessionRequest.CreateSession(authToken, out userID, out sessionExpires, out dummy);
                    Debug.Assert(String.IsNullOrEmpty(dummy));
                }
            }

            if (!String.IsNullOrEmpty(sessionKey) && !String.IsNullOrEmpty(userID)) {
                if (String.IsNullOrEmpty(pageUserID) == false) {
                    sessionType = FacebookSessionType.PresencePage;
                }
                InitializeSessionKey(sessionKey, sessionExpires, sessionType);
                InitializeUserID(userID, pageUserID);
            }
            else {
                redirectUrl = String.Format(FacebookLoginUrl, ApplicationKey);
            }

            if ((redirectUrl == null) && (Application.IsApplicationAdded == false)) {
                redirectUrl = String.Format(FacebookAddAppUrl, ApplicationKey);
            }

            if (_referrer == null) {
                if (request.UrlReferrer == null) {
                    _referrer = request.Url.AbsoluteUri;
                }
                else {
                    _referrer = request.UrlReferrer.AbsoluteUri;
                }
            }

            return redirectUrl;
        }

        protected internal override void LoadState(object state) {
            Debug.Assert(state != null);
            Debug.Assert(state is Triplet);

            Triplet t = (Triplet)state;
            Pair sessionState = (Pair)t.First;
            Pair userState = (Pair)t.Second;

            _sessionKeyState = (string)sessionState.First;
            _sessionExpiresState = (bool)sessionState.Second;

            _userIDState = (string)userState.First;
            _pageUserIDState = (string)userState.Second;

            _referrer = (string)t.Third;

            _stateLoaded = true;
        }

        protected internal override object SaveState() {
            Pair sessionState = new Pair(SessionKey, SessionExpires);
            Pair userState = new Pair(UserID, PageUserID);

            return new Triplet(sessionState, userState, _referrer);
        }

        public string ResolveUrl(HttpContext context, string url) {
            Uri uri = new Uri(url, UriKind.RelativeOrAbsolute);

            if (uri.IsAbsoluteUri == false) {
                Uri referrerUri = new Uri(_referrer, UriKind.Absolute);
                Uri resolvedUri = new Uri(referrerUri, uri);
                url = resolvedUri.AbsoluteUri;

                if (Application.Session.SessionType == FacebookSessionType.PresencePage) {
                    int queryIndex = url.IndexOf('?');

                    url += queryIndex >= 0 ? "&" : "?";
                    url += "fb_page_id=" + Application.UserID;
                }
            }
            return url;
        }
    }
}
